#include <iostream>
#include <fstream>
#include <iomanip>
#include <cassert>
#include <string>
#include "database.h"
#include "frameworkmgr.h"
#include "cnotify.h"
#include "timer.h"
#define DB_PATH "../db/"
static database *g_Database = nullptr;
int database::Process(CAgrcList *message, RspMsg *outmessage, int iModule, int iCmd)
{
    PROCESS_BEGIN(iCmd)
    PROCESS_CALL(CMD_MSG_DB_INIT, DbInit)
    PROCESS_CALL(CMD_SYS_SHUT_DOWN, DbSync)
    PROCESS_CALL(CMD_MSG_DB_SAVE, DbSync)
    PROCESS_END()
}

int database::DbInit(CAgrcList *message, RspMsg *outmessage,
                     int iModule, int iCmd)
{
    dbinit();
    return SUCCESS;
}
int database::DbSync(CAgrcList *message, RspMsg *outmessage,
                     int iModule, int iCmd)
{
    for (auto &iter : m_mapJsonObjectRef)
    {
        {
            std::ofstream outfile(DB_PATH + iter.first + ".json");
            if (!outfile.is_open())
            {
                LOG_ERROR("write %s.json is failed.", iter.first);
                continue;
            }
            outfile << std::setw(4) << iter.second;
        }
    }
    return SUCCESS;
}
database::~database()
{
    DbSync(nullptr, nullptr, 0, 0);
}
int database::Init()
{
    Cnotify *obj =
        reinterpret_cast<Cnotify *>(g_objKernel->InterFace(MODELU_NOTIFY));
    if (obj)
        obj->RegReceiver(MODELU_DB_MGR, new REGNOTIFY(this, "database"));
    return 0;
}
void database::dbinit()
{
    std::map<const char *, ObjModule *> list;
    g_objKernel->obListGet(list);
    for (auto &iter : list)
    {
        {
            std::string fileName;
            fileName.append(DB_PATH);
            fileName.append(iter.second->name);
            fileName.append(".json");
            std::ifstream infile(fileName.c_str());
            if (!infile.is_open())
            {
                continue;
            }
            Json inJson;
            infile >> inJson;
            m_mapJsonObjectRef.insert(
                std::pair<std::string, Json>(iter.second->name, std::move(inJson)));
        }
    }
    TimerManager *obj =
        reinterpret_cast<TimerManager *>(g_objKernel->InterFace(MODELU_TIMER));
    if (obj)
        obj->AddTimer("dbTimer",
                      new Timer([](void *args) -> void * {
                          Cnotify *obj =
                              reinterpret_cast<Cnotify *>(args);
                          if (obj)
                              obj->NotifyA(nullptr, nullptr, 0, CMD_MSG_DB_SAVE);
                          return (void *)0;
                      },
                                g_objKernel->InterFace(MODELU_NOTIFY), 5000, Timer::CIRCLE));
}
void db_Init()
{
    if (isExistPath(DB_PATH) != 0)
    {
        mkdirPath(DB_PATH);
        return;
    }
    if (g_Database != nullptr)
        g_Database->dbinit();
}
Json &objDbGet(const char *name)
{
    LVOS_ASSERT((g_Database != nullptr));
    auto iter = g_Database->m_mapJsonObjectRef.find(name);
    if (iter != g_Database->m_mapJsonObjectRef.end())
    {
        return iter->second;
    }

    Json cjson;
    g_Database->m_mapJsonObjectRef.insert(
        std::pair<std::string, Json>(name, std::move(cjson)));
    return g_Database->m_mapJsonObjectRef[name];
}
database::database()
{
    g_Database = this;
}
REG_TO_FRAMEWORK(TABLE_ONE, MODELU_KERNEL, database, MODELU_DB_MGR)